home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_200 / 216_02 / zm.c < prev    next >
Text File  |  1980-01-01  |  10KB  |  526 lines

  1. /*
  2.  *   Z M . C
  3.  *    ZMODEM protocol primitives
  4.  *    8-16-86  Chuck Forsberg Omen Technology Inc
  5.  *
  6.  * Entry point Functions:
  7.  *    zsbhdr(type, hdr) send binary header
  8.  *    zshhdr(type, hdr) send hex header
  9.  *    zgethdr(hdr, eflag) receive header - binary or hex
  10.  *    zsdata(buf, len, frameend) send data
  11.  *    zrdata(buf, len) receive data
  12.  *    stohdr(pos) store position data in Txhdr
  13.  *    long rclhdr(hdr) recover position offset from header
  14.  */
  15.  
  16. #ifndef CANFDX
  17. #include "zmodem.h"
  18. int Rxtimeout = 100;        /* Tenths of seconds to wait for something */
  19. #endif
  20.  
  21. static char *frametypes[] = {
  22.     "Carrier Lost",        /* -3 */
  23.     "TIMEOUT",        /* -2 */
  24.     "ERROR",        /* -1 */
  25. #define FTOFFSET 3
  26.     "ZRQINIT",
  27.     "ZRINIT",
  28.     "ZSINIT",
  29.     "ZACK",
  30.     "ZFILE",
  31.     "ZSKIP",
  32.     "ZNAK",
  33.     "ZABORT",
  34.     "ZFIN",
  35.     "ZRPOS",
  36.     "ZDATA",
  37.     "ZEOF",
  38.     "ZFERR",
  39.     "ZCRC",
  40.     "ZCHALLENGE",
  41.     "ZCOMPL",
  42.     "ZCAN",
  43.     "ZFREECNT",
  44.     "ZCOMMAND",
  45.     "ZSTDERR",
  46.     "xxxxx"
  47. #define FRTYPES 22    /* Total number of frame types in this array */
  48.             /*  not including psuedo negative entries */
  49. };
  50.  
  51. /* Send ZMODEM binary header hdr of type type */
  52. zsbhdr(type, hdr)
  53. register char *hdr;
  54. {
  55.     register n;
  56.     register unsigned short crc;
  57.  
  58.     vfile("zsbhdr: %s %lx", frametypes[type+FTOFFSET], rclhdr(hdr));
  59.     if (type == ZDATA)
  60.         for (n = Znulls; --n >=0; )
  61.             zsendline(0);
  62.  
  63.     xsendline(ZPAD); xsendline(ZDLE); xsendline(ZBIN);
  64.  
  65.     zsendline(type); crc = updcrc(type, 0);
  66.  
  67.     for (n=4; --n >= 0;) {
  68.         zsendline(*hdr);
  69.         crc = updcrc((0377& *hdr++), crc);
  70.     }
  71.     crc = updcrc(0,updcrc(0,crc));
  72.     zsendline(crc>>8);
  73.     zsendline(crc);
  74.     if (type != ZDATA)
  75.         flushmo();
  76. }
  77.  
  78. /* Send ZMODEM HEX header hdr of type type */
  79. zshhdr(type, hdr)
  80. register char *hdr;
  81. {
  82.     register n;
  83.     register unsigned short crc;
  84.  
  85.     vfile("zshhdr: %s %lx", frametypes[type+FTOFFSET], rclhdr(hdr));
  86.     sendline(ZPAD); sendline(ZPAD); sendline(ZDLE); sendline(ZHEX);
  87.     zputhex(type);
  88.  
  89.     crc = updcrc(type, 0);
  90.     for (n=4; --n >= 0;) {
  91.         zputhex(*hdr); crc = updcrc((0377& *hdr++), crc);
  92.     }
  93.     crc = updcrc(0,updcrc(0,crc));
  94.     zputhex(crc>>8); zputhex(crc);
  95.  
  96.     /* Make it printable on remote machine */
  97.     sendline(015); sendline(012);
  98.     /*
  99.      * Uncork the remote in case a fake XOFF has stopped data flow
  100.      */
  101.     if (type != ZFIN)
  102.         sendline(021);
  103.     flushmo();
  104. }
  105.  
  106. /*
  107.  * Send binary array buf of length length, with ending ZDLE sequence frameend
  108.  */
  109. zsdata(buf, length, frameend)
  110. register char *buf;
  111. {
  112.     register unsigned short crc;
  113.  
  114.     vfile("zsdata: length=%d end=%x", length, frameend);
  115.     crc = 0;
  116.     for (;--length >= 0;) {
  117.         zsendline(*buf);
  118.         crc = updcrc((0377& *buf++), crc);
  119.     }
  120.     xsendline(ZDLE); xsendline(frameend);
  121.     crc = updcrc(frameend, crc);
  122.  
  123.     crc = updcrc(0,updcrc(0,crc));
  124.     zsendline(crc>>8);
  125.     zsendline(crc);
  126.     if (frameend == ZCRCW) {
  127.         xsendline(XON);  flushmo();
  128.     }
  129. }
  130.  
  131. /*
  132.  * Receive array buf of max length with ending ZDLE sequence
  133.  *  and CRC.  Returns the ending character or error code.
  134.  */
  135. zrdata(buf, length)
  136. register char *buf;
  137. {
  138.     register c;
  139.     register unsigned short crc;
  140.     register d;
  141.  
  142.     crc = Rxcount = 0;
  143.     for (;;) {
  144.         if ((c = zdlread()) & ~0377) {
  145. crcfoo:
  146.             switch (c) {
  147.             case GOTCRCE:
  148.             case GOTCRCG:
  149.             case GOTCRCQ:
  150.             case GOTCRCW:
  151.                 crc = updcrc((d=c)&0377, crc);
  152.                 if ((c = zdlread()) & ~0377)
  153.                     goto crcfoo;
  154.                 crc = updcrc(c, crc);
  155.                 if ((c = zdlread()) & ~0377)
  156.                     goto crcfoo;
  157.                 crc = updcrc(c, crc);
  158.                 if (crc & 0xFFFF) {
  159.                     zperr("Bad data CRC %x", crc);
  160.                     return ERROR;
  161.                 }
  162.                 vfile("zrdata: cnt = %d ret = %x", Rxcount, d);
  163.                 return d;
  164.             case GOTCAN:
  165.                 zperr("ZMODEM: Sender Canceled");
  166.                 return ZCAN;
  167.             case TIMEOUT:
  168.                 zperr("ZMODEM data TIMEOUT");
  169.                 return c;
  170.             default:
  171.                 zperr("ZMODEM bad data subpacket ret=%x", c);
  172.                 return c;
  173.             }
  174.         }
  175.         if (--length < 0) {
  176.             zperr("ZMODEM data subpacket too long");
  177.             return ERROR;
  178.         }
  179.         ++Rxcount;
  180.         *buf++ = c;
  181.         crc = updcrc(c, crc);
  182.         continue;
  183.     }
  184. }
  185.  
  186. /*
  187.  * Read a ZMODEM header to hdr, either binary or hex.
  188.  *  eflag controls local display of non zmodem characters:
  189.  *    0:  no display
  190.  *    1:  display printing characters only
  191.  *    2:  display all non ZMODEM characters
  192.  *  On success, set Zmodem to 1 and return type of header.
  193.  *   Otherwise return negative on error
  194.  */
  195. zgethdr(hdr, eflag)
  196. char *hdr;
  197. {
  198.     register c, n, cancount;
  199.  
  200.     n = Baudrate;    /* Max characters before start of frame */
  201.     cancount = 5;
  202. again:
  203.     Rxframeind = Rxtype = 0;
  204.     switch (c = noxread7()) {
  205.     case RCDO:
  206.     case TIMEOUT:
  207.         goto fifi;
  208.     case CAN:
  209.         if (--cancount <= 0) {
  210.             c = ZCAN; goto fifi;
  211.         }
  212.     /* **** FALL THRU TO **** */
  213.     default:
  214. agn2:
  215.         if ( --n == 0) {
  216.             zperr("ZMODEM Garbage count exceeded");
  217.             return(ERROR);
  218.         }
  219.         if (eflag && ((c &= 0177) & 0140))
  220.             bttyout(c);
  221.         else if (eflag > 1)
  222.             bttyout(c);
  223.         if (c != CAN)
  224.             cancount = 5;
  225.         goto again;
  226.     case ZPAD:        /* This is what we want. */
  227.         break;
  228.     }
  229.     cancount = 5;
  230. splat:
  231.     switch (c = noxread7()) {
  232.     case ZPAD:
  233.         goto splat;
  234.     case RCDO:
  235.     case TIMEOUT:
  236.         goto fifi;
  237.     default:
  238.         goto agn2;
  239.     case ZDLE:        /* This is what we want. */
  240.         break;
  241.     }
  242.  
  243.     switch (c = noxread7()) {
  244.     case RCDO:
  245.     case TIMEOUT:
  246.         goto fifi;
  247.     case ZBIN:
  248.         Rxframeind = ZBIN;
  249.         c =  zrbhdr(hdr);
  250.         break;
  251.     case ZHEX:
  252.         Rxframeind = ZHEX;
  253.         c =  zrhhdr(hdr);
  254.         break;
  255.     case CAN:
  256.         if (--cancount <= 0) {
  257.             c = ZCAN; goto fifi;
  258.         }
  259.         goto agn2;
  260.     default:
  261.         goto agn2;
  262.     }
  263.     Rxpos = hdr[ZP3] & 0377;
  264.     Rxpos = (Rxpos<<8) + (hdr[ZP2] & 0377);
  265.     Rxpos = (Rxpos<<8) + (hdr[ZP1] & 0377);
  266.     Rxpos = (Rxpos<<8) + (hdr[ZP0] & 0377);
  267. fifi:
  268.     switch (c) {
  269.     case GOTCAN:
  270.         c = ZCAN;
  271.     /* **** FALL THRU TO **** */
  272.     case ZNAK:
  273.     case ZCAN:
  274.     case ERROR:
  275.     case TIMEOUT:
  276.     case RCDO:
  277.         zperr("ZMODEM: Got %s %s", frametypes[c+FTOFFSET],
  278.           (c >= 0) ? "header" : "error");
  279.     /* **** FALL THRU TO **** */
  280.     default:
  281.         if (c >= -3 && c <= FRTYPES)
  282.             vfile("zgethdr: %s %lx", frametypes[c+FTOFFSET], Rxpos);
  283.         else
  284.             vfile("zgethdr: %d %lx", c, Rxpos);
  285.     }
  286.     return c;
  287. }
  288.  
  289. /* Receive a binary style header (type and position) */
  290. zrbhdr(hdr)
  291. register char *hdr;
  292. {
  293.     register c, n;
  294.     register unsigned short crc;
  295.  
  296.     if ((c = zdlread()) & ~0377)
  297.         return c;
  298.     Rxtype = c;
  299.     crc = updcrc(c, 0);
  300.  
  301.     for (n=4; --n >= 0;) {
  302.         if ((c = zdlread()) & ~0377)
  303.             return c;
  304.         crc = updcrc(c, crc);
  305.         *hdr++ = c;
  306.     }
  307.     if ((c = zdlread()) & ~0377)
  308.         return c;
  309.     crc = updcrc(c, crc);
  310.     if ((c = zdlread()) & ~0377)
  311.         return c;
  312.     crc = updcrc(c, crc);
  313.     if (crc & 0xFFFF) {
  314.         zperr("Bad Header CRC"); return ERROR;
  315.     }
  316.     Zmodem = 1;
  317.     return Rxtype;
  318. }
  319.  
  320. /* Receive a hex style header (type and position) */
  321. zrhhdr(hdr)
  322. char *hdr;
  323. {
  324.     register c;
  325.     register unsigned short crc;
  326.     register n;
  327.  
  328.     if ((c = zgethex()) < 0)
  329.         return c;
  330.     Rxtype = c;
  331.     crc = updcrc(c, 0);
  332.  
  333.     for (n=4; --n >= 0;) {
  334.         if ((c = zgethex()) < 0)
  335.             return c;
  336.         crc = updcrc(c, crc);
  337.         *hdr++ = c;
  338.     }
  339.     if ((c = zgethex()) < 0)
  340.         return c;
  341.     crc = updcrc(c, crc);
  342.     if ((c = zgethex()) < 0)
  343.         return c;
  344.     crc = updcrc(c, crc);
  345.     if (crc & 0xFFFF) {
  346.         zperr("Bad Header CRC"); return ERROR;
  347.     }
  348.     if (readline(1) == '\r')    /* Throw away possible cr/lf */
  349.         readline(1);
  350.     Zmodem = 1; return Rxtype;
  351. }
  352.  
  353. /* Send a byte as two hex digits */
  354. zputhex(c)
  355. register c;
  356. {
  357.     static char    digits[]    = "0123456789abcdef";
  358.  
  359.     if (Verbose>4)
  360.         vfile("zputhex: %x", c);
  361.     sendline(digits[(c&0xF0)>>4]);
  362.     sendline(digits[(c)&0xF]);
  363. }
  364.  
  365. /*
  366.  * Send character c with ZMODEM escape sequence encoding.
  367.  *  Escape XON, XOFF. Escape CR following @ (Telenet net escape)
  368.  */
  369. zsendline(c)
  370. register c;
  371. {
  372.     static lastsent;
  373.  
  374.     switch (c & 0377) {
  375.     case ZDLE:
  376.         xsendline(ZDLE);
  377.         xsendline (lastsent = (c ^= 0100));
  378.         break;
  379.     case 015:
  380.     case 0215:
  381.         if ((lastsent & 0177) != '@')
  382.             goto sendit;
  383.     /* **** FALL THRU TO **** */
  384.     case 020:
  385.     case 021:
  386.     case 023:
  387.     case 0220:
  388.     case 0221:
  389.     case 0223:
  390. #ifdef ZKER
  391.         if (Zctlesc<0)
  392.             goto sendit;
  393. #endif
  394.         xsendline(ZDLE);
  395.         c ^= 0100;
  396. sendit:
  397.         xsendline(lastsent = c);
  398.         break;
  399.     default:
  400. #ifdef ZKER
  401.         if (Zctlesc>0 && ! (